#include "pch.h"
#include "general_settings.h"
#include "auto_start_helper.h"
#include <common/settings_helpers.h>
#include "powertoy_module.h"
#include <common/windows_colors.h>

static std::wstring settings_theme = L"system";

json::JsonObject load_general_settings() {
  auto loaded = PTSettingsHelper::load_general_settings();
  settings_theme = loaded.GetNamedString(L"theme", L"system");
  if (settings_theme != L"dark" && settings_theme != L"light") { 
    settings_theme = L"system";
  }
  return loaded;
}

json::JsonObject get_general_settings() {
  json::JsonObject result;
  const bool startup = is_auto_start_task_active_for_this_user();
  result.SetNamedValue(L"startup", json::value(startup));

  json::JsonObject enabled;
  for (auto&[name, powertoy] : modules()) {
    enabled.SetNamedValue(name, json::value(powertoy.is_enabled()));
  }
  result.SetNamedValue(L"enabled", std::move(enabled));

  result.SetNamedValue(L"theme", json::value(settings_theme));
  result.SetNamedValue(L"system_theme", json::value(WindowsColors::is_dark_mode() ? L"dark" : L"light"));
  result.SetNamedValue(L"powertoys_version", json::value(get_product_version()));
  return result;
}

void apply_general_settings(const json::JsonObject& general_configs) {
  if (json::has(general_configs, L"startup", json::JsonValueType::Boolean)) {
    const bool startup = general_configs.GetNamedBoolean(L"startup");
    const bool current_startup = is_auto_start_task_active_for_this_user();
    if (current_startup != startup) {
      if (startup) {
        enable_auto_start_task_for_this_user();
      } else {
        disable_auto_start_task_for_this_user();
      }
    }
  }
  if (json::has(general_configs, L"enabled")) {
    for (const auto& enabled_element : general_configs.GetNamedObject(L"enabled")) {
      const auto value = enabled_element.Value();
      if (value.ValueType() != json::JsonValueType::Boolean) {
        continue;
      }
      const std::wstring name{enabled_element.Key().c_str()};
      const bool found = modules().find(name) != modules().end();
      if (!found) {
        continue;
      }
      const bool module_inst_enabled = modules().at(name).is_enabled();
      const bool target_enabled = value.GetBoolean();
      if (module_inst_enabled == target_enabled) {
        continue;
      }
      if (target_enabled) {
        modules().at(name).enable();
      } else {
        modules().at(name).disable();
      }
    }
  }
  if (json::has(general_configs, L"theme", json::JsonValueType::String)) {
    settings_theme = general_configs.GetNamedString(L"theme");
  }
  json::JsonObject save_settings = get_general_settings();
  PTSettingsHelper::save_general_settings(save_settings);
}

void start_initial_powertoys() {
  bool only_enable_some_powertoys = false;

  std::unordered_set<std::wstring> powertoys_to_enable;

  json::JsonObject general_settings;
  try {
    general_settings = load_general_settings();
    json::JsonObject enabled = general_settings.GetNamedObject(L"enabled");
    for (const auto & enabled_element : enabled) {
      if (enabled_element.Value().GetBoolean()) {
        // Enable this powertoy.
        powertoys_to_enable.emplace(enabled_element.Key());
      }
    }
    only_enable_some_powertoys = true;
  }
  catch (...) {
    // Couldn't read the general settings correctly.
    // Load all powertoys.
    // TODO: notify user about invalid json config
    only_enable_some_powertoys = false;
  }

  for (auto&[name, powertoy] : modules()) {
    if (only_enable_some_powertoys) {
      if (powertoys_to_enable.find(name)!=powertoys_to_enable.end()) {
        powertoy.enable();
      }
    } else {
      powertoy.enable();
    }
  }
}
